import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {NzMessageService} from "ng-zorro-antd/message";
import {NzSafeAny} from "ng-zorro-antd/core/types";
import {filter, map, Observable} from "rxjs";
import {localUrl} from "../../../environments/environment";
import {DateUtil} from "../../util/DateUtil";
import {CLIENT_VERSION, SYSTEM_ID, TENANT_ID} from "../../config/constant";
import {AdminInfo} from "../../model/AdminInfo";
import {SpUtil} from "../../util/SpUtil";
import {Router} from "@angular/router";

export interface HttpCustomConfig {
  showLoading: boolean
}

export interface ActionResult<T> {
  code: number;
  msg: string;
  data: T;
}

@Injectable({
  providedIn: 'root'
})
export class BaseHttpService {
  uri: string;

  protected constructor(private router: Router, public http: HttpClient, public message: NzMessageService) {
    this.uri = localUrl;
  }

  post<T>(path: string, param: NzSafeAny, config: HttpCustomConfig): Observable<ActionResult<T>> {
    config.showLoading = true;
    const reqParam = this.getParam(param);
    return this.http.post<ActionResult<T>>(path, reqParam).pipe(this.resultHandle<T>(config));
  }

  getUrl(path: string, ignoreUri: boolean): string {
    if (ignoreUri) {
      return path;
    }
    return this.uri + path;
  }

  getParam(param: NzSafeAny): NzSafeAny {

    const admin: AdminInfo = SpUtil.getAdminInfo();

    return {
      tenantId: TENANT_ID,
      operatorId: admin.adminId,
      systemId: SYSTEM_ID,
      clientTime: DateUtil.reqDate(new Date()),
      token: admin.token,
      clientVersion: CLIENT_VERSION,
      request: param
    };
  }

  resultHandle<T>(config: HttpCustomConfig): (observable: Observable<ActionResult<T>>) => Observable<ActionResult<T>> {
    return (observable: Observable<ActionResult<T>>) => {
      return observable.pipe(
        map(item => {
          return this.handlePre(item, config);
        }),
        filter(item => {
          return this.handleFilter(item, config);
        }),
        map(item => {
          return this.handleSuccess(item, config);
        })
      );
    };
  }

  handlePre<T>(item: ActionResult<T>, config: HttpCustomConfig): ActionResult<T> {
    config.showLoading = false;
    return item;
  }

  handleFilter<T>(item: ActionResult<T>, config: HttpCustomConfig): boolean {
    if (item.code === 506) {
      this.router.navigateByUrl('welcome').then();
      return false;
    } else if (item.code !== 200) {
      this.message.error(item.msg);
      return false;
    }
    return true;
  }

  handleSuccess<T>(item: ActionResult<T>, config: HttpCustomConfig): ActionResult<T> {
    return item;
  }

}
